﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace CrayonsBox.Drawing
{
    public class DepricatedSelection : Document.Drawable
    {
        public enum HandleType //clockwise
        {
            TopLeft,
            Top,
            TopRight,
            Right,
            BottomRight,
            Bottom,
            BottomLeft,
            Left,
            None
        }

        public event EventHandler OnSelectStateChanged;

        private Point[] m_handles;
        private HandleType m_grabbed;

        public Boolean IsFreeResize { get; set; }

        public override Boolean IsSelected
        {
            get
            {
                return base.IsSelected;
            }

            set
            {
                bool stateChanged = (base.IsSelected != value);
                base.IsSelected = value;
                if (stateChanged && OnSelectStateChanged != null)
                {
                    OnSelectStateChanged(this, new EventArgs());
                }

            }
        }

        public override Rectangle Boundary
        {
            get
            {
                return base.Boundary;
            }

            set
            {
                base.Boundary = value;

                //north west
                m_handles[0].X = base.Boundary.Left;
                m_handles[0].Y = base.Boundary.Top;

                //north
                m_handles[1].X = (base.Boundary.Left + base.Boundary.Right) / 2;
                m_handles[1].Y = base.Boundary.Top;

                //north-east
                m_handles[2].X = base.Boundary.Right;
                m_handles[2].Y = base.Boundary.Top;

                //east
                m_handles[3].X = base.Boundary.Right;
                m_handles[3].Y = (base.Boundary.Top + base.Boundary.Bottom) / 2;

                //south-east
                m_handles[4].X = base.Boundary.Right;
                m_handles[4].Y = base.Boundary.Bottom;

                //south
                m_handles[5].X = (base.Boundary.Left + base.Boundary.Right) / 2;
                m_handles[5].Y = base.Boundary.Bottom;

                //south-west
                m_handles[6].X = base.Boundary.Left;
                m_handles[6].Y = base.Boundary.Bottom;

                //west
                m_handles[7].X = base.Boundary.Left;
                m_handles[7].Y = (base.Boundary.Top + base.Boundary.Bottom) / 2;
            }
        }

        public Point[] Handles
        {
            get { return m_handles; }
        }

        public HandleType GrabbedHandle
        {
            get
            {
                return m_grabbed;
            }

            set
            {
                if (this.IsSelected)
                    m_grabbed = value;
                else
                    m_grabbed = HandleType.None;
            }
        }

        public Point GrabbedHandlePosition
        {
            set
            {
                if (m_grabbed != HandleType.None)
                {

                    if(IsFreeResize)
                        AutoSwitchHandle(value);

                    int left = Boundary.Left;
                    int top = Boundary.Top;
                    int right = Boundary.Right;
                    int bottom = Boundary.Bottom;

                    if (m_grabbed == HandleType.Left || m_grabbed == HandleType.TopLeft || m_grabbed == HandleType.BottomLeft)
                        left = value.X;

                    if (m_grabbed == HandleType.Top || m_grabbed == HandleType.TopLeft || m_grabbed == HandleType.TopRight)
                        top = value.Y;

                    if (m_grabbed == HandleType.Right || m_grabbed == HandleType.TopRight || m_grabbed == HandleType.BottomRight)
                        right = value.X;

                    if (m_grabbed == HandleType.Bottom || m_grabbed == HandleType.BottomLeft || m_grabbed == HandleType.BottomRight)
                        bottom = value.Y;

                    if (top > bottom) bottom = top;
                    if (left > right) right = left;
                  
                    Boundary = Rectangle.FromLTRB(left, top, right, bottom);
                }
            }
        }

        public DepricatedSelection(Document doc) : base(doc)
        {
            m_rect = new Rectangle(0, 0, 0, 0);
            m_handles = new Point[8];
            IsVisible = true;
            IsFreeResize = true;
        }

        protected void AutoSwitchHandle(Point mp)
        {
            if (m_grabbed == DepricatedSelection.HandleType.Bottom)
            {
                if (Boundary.Height == 0 && mp.Y < Boundary.Top)
                    GrabbedHandle = DepricatedSelection.HandleType.Top;
            }
            else if (m_grabbed == DepricatedSelection.HandleType.Top)
            {
                if (Boundary.Height == 0 && mp.Y > Boundary.Bottom)
                    GrabbedHandle = DepricatedSelection.HandleType.Bottom;
            }
            else if (m_grabbed == DepricatedSelection.HandleType.Left)
            {
                if (Boundary.Width == 0 && mp.X > Boundary.Right)
                    GrabbedHandle = DepricatedSelection.HandleType.Right;
            }
            else if (m_grabbed == DepricatedSelection.HandleType.Right)
            {
                if (Boundary.Width == 0 && mp.X < Boundary.Left)
                    GrabbedHandle = DepricatedSelection.HandleType.Left;
            }
            else if (m_grabbed == DepricatedSelection.HandleType.TopLeft)
            {
                if (Boundary.Width == 0 && (mp.X > Boundary.Right && mp.Y < Boundary.Bottom))
                    GrabbedHandle = DepricatedSelection.HandleType.TopRight;
                else
                {
                    if (Boundary.Height == 0 && (mp.Y > Boundary.Bottom && mp.X < Boundary.Right))
                        GrabbedHandle = DepricatedSelection.HandleType.BottomLeft;
                }
            }
            else if (m_grabbed == DepricatedSelection.HandleType.TopRight)
            {
                if (Boundary.Width == 0 && (mp.X < Boundary.Left && mp.Y < Boundary.Bottom))
                    GrabbedHandle = DepricatedSelection.HandleType.TopLeft;
                else
                {
                    if (Boundary.Height == 0 && (mp.Y > Boundary.Bottom && mp.X > Boundary.Left))
                        GrabbedHandle = DepricatedSelection.HandleType.BottomRight;
                }
            }
            else if (m_grabbed == DepricatedSelection.HandleType.BottomLeft)
            {
                if (Boundary.Width == 0 && (mp.X > Boundary.Right && mp.Y > Boundary.Top))
                    GrabbedHandle = DepricatedSelection.HandleType.BottomRight;
                else
                {
                    if (Boundary.Height == 0 && (mp.Y < Boundary.Top && mp.X < Boundary.Right))
                        GrabbedHandle = DepricatedSelection.HandleType.TopLeft;
                }
            }
            else if (m_grabbed == DepricatedSelection.HandleType.BottomRight)
            {
                if (Boundary.Width == 0 && (mp.X < Boundary.Left && mp.Y > Boundary.Top))
                    GrabbedHandle = DepricatedSelection.HandleType.BottomLeft;
                else
                {
                    if (Boundary.Height == 0 && (mp.Y < Boundary.Top && mp.X > Boundary.Left))
                        GrabbedHandle = DepricatedSelection.HandleType.TopRight;
                }
            }
        }

        public override void Draw()
        {
            if (!IsVisible || (Boundary.Height * Boundary.Width) == 0)
                return;

            float[] dashValues = { 5, 5 };
            Pen blpen = new Pen(Color.FromArgb(51, 153, 255), 1);
            blpen.DashPattern = dashValues;
            SolidBrush bbr = new SolidBrush(Color.FromArgb(51, 153, 255));

            Pen bkpen = new Pen(Color.Black, 1);
            SolidBrush wbr = new SolidBrush(Color.White);

            Rectangle tmpRec = new Rectangle(
                (int)(Boundary.X * Doc.ZoomRate),
                (int)(Boundary.Y * Doc.ZoomRate),
                (int)(Boundary.Width * Doc.ZoomRate),
                (int)(Boundary.Height * Doc.ZoomRate)
            );

            Matrix m = Doc.Painter.Transform;

            this.Doc.Painter.ResetTransform();

            this.Doc.Painter.TranslateTransform(-Doc.Viewport.X * Doc.ZoomRate, -Doc.Viewport.Y * Doc.ZoomRate);

            Doc.Painter.DrawLine(blpen, tmpRec.Left, tmpRec.Top, tmpRec.Right, tmpRec.Top);
            Doc.Painter.DrawLine(blpen, tmpRec.Right, tmpRec.Top, tmpRec.Right, tmpRec.Bottom);
            Doc.Painter.DrawLine(blpen, tmpRec.Right, tmpRec.Bottom, tmpRec.Left, tmpRec.Bottom);
            Doc.Painter.DrawLine(blpen, tmpRec.Left, tmpRec.Bottom, tmpRec.Left, tmpRec.Top);

            if (IsSelected)
            {
                foreach (Point p in Handles)
                {
                    Doc.Painter.FillRectangle(wbr, (int)(p.X * Doc.ZoomRate) - 2, (int)(p.Y * Doc.ZoomRate) - 2, 5, 5);
                    Doc.Painter.DrawRectangle(bkpen, (int)(p.X * Doc.ZoomRate) - 2, (int)(p.Y * Doc.ZoomRate) - 2, 4, 4);
                }
            }

            Doc.Painter.Transform = m;
        }
    }

    public class SelectionCollection
    {
        private DepricatedSelection m_selected;
        private List<DepricatedSelection> m_selections;
        private Document m_document;
        
        public int Count
        {
            get
            {
                return m_selections.Count;
            }
        }

        public DepricatedSelection this[int idx]
        {
            get
            {
                return m_selections[idx];
            }

            set
            {
                m_selections[idx] = value;
            }
        }

        public DepricatedSelection SelectedSelection 
        { 
            get 
            { 
                return m_selected; 
            } 
        }

        public SelectionCollection(Document attachDocument)
        {
            m_document = attachDocument;
            m_selections = new List<DepricatedSelection>();
        }

        public void AddSelection(DepricatedSelection sel)
        {
            if (sel != null && !m_selections.Contains(sel))
            {
                m_selections.Add(sel);
                if (m_selected != sel  && sel.IsSelected)
                {
                    if (m_selected != null)
                        m_selected.IsSelected = false;
                    m_selected = sel;
                }
                sel.OnSelectStateChanged += new EventHandler(HandleSelectStateChanged);
            }
        }

        protected void HandleSelectStateChanged(object sender, EventArgs e)
        {
            DepricatedSelection s = sender as DepricatedSelection;
            
            if(m_selected != null)
                m_selected.IsSelected = false;
            
            if(s.IsSelected)
                m_selected = s;
        }
    }
}
